﻿using System;
using System.Collections.Generic;
using System.Linq;
using Citi.EmailSender.Domain.NHibernate;
using NHibernate;
using NHibernate.Linq;
using System.Runtime.Serialization;

namespace Citi.EmailSender.Domain.Repository
{
    [Serializable()]
    [DataContractAttribute(IsReference = true)]
    public class RepositoryBase<T> : IRepository<T> //where T : EntityBase<T>
    {
        private static ISession session;

        protected static ISession Session
        {
            get
            {
                if (session == null || !session.IsOpen)
                {
                    session = new SessionFactory().CreateSessionFactory<T>().OpenSession();
                    //session.FlushMode = FlushMode.Always;
                    return session;
                }

                return session;
            }
        }

        public virtual void Save(T entity)
        {
            try
            {
                Session.SaveOrUpdate(entity);
                Session.Flush();
                Session.Refresh(entity);
            }
            catch (Exception ex)
            {
                //Session.Refresh(entity);
            }
        }

        public virtual void Save(IEnumerable<T> entities)
        {
            try
            {
                using (var transaction = Session.BeginTransaction())
                {
                    try
                    {
                        Session.Flush();
                    }
                    catch { }

                    foreach (var entity in entities)
                    {
                        Session.SaveOrUpdate(entity);
                        Session.Refresh(entity);
                    }

                    try
                    {
                        Session.Flush();
                    }
                    catch { }

                    transaction.Commit();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public virtual void Delete(T entity)
        {
            try
            {
                Session.Delete(entity);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public virtual void ExecuteQuery(IEnumerable<string> clause)
        {
            try
            {
                using (ISession session = Session)
                using (var transaction = session.BeginTransaction())
                {
                    foreach (var item in clause)
                    {
                        var query = session.CreateQuery(item).ExecuteUpdate();
                    }

                    transaction.Commit();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public virtual T GetById(int id)
        {
            return Session.Get<T>(id);
        }

        public virtual IQueryable<T> GetAll()
        {
            return Session.Query<T>();
        }
    }
}
